/**
* @description 全局路由跳转方法
* router有四个重要的方法
* routerTo(object) -->路由跳转
* routerBack() -->页面返回
* routerRedirect() -->登录之后页面重定向
*/

import store from '@/store'
import { isString, isObject } from '@/utils/is.js'
import { setObjToString } from '@/utils/common.js'

const routeEnum = {
  loginPath: '/pages/login/index',
  indexPath: '/pages/index/index'
}

// tabbar的路由url
const tabbarPaths = ['pages/index/index', 'pages/category/index']

// 获取页面路由
export const getRoute = function() {
  const routes = getCurrentPages()
  if (!routes.length) {
    return {
      route: '',
      query: ''
    }
  }
  // 当前的页面路由
  const currentRoute = routes[routes.length - 1]
  return {
    route: currentRoute.route,
    query: currentRoute.options,
    routes
  }
}

/**
* @description 判断是否登录
* @returns {Boolean} true--已登录，false--未登录
*/
export const isLogin = function() {
  const token = store.getters.token
  return !!token
}


/**
* @description 登录弹窗
* @returns {Boolean} true--弹窗 false--直接去登录页
*/
export const hasModal = function(modal) {
  if (modal) {
    // 弹窗询问是否去登录页
    uni.showModal({
      title: '登录提示',
      content: '你尚未登录！',
      confirmText: '去登录',
      cancelText: '继续逛逛',
      success: ({ confirm, cancel }) => {
        confirm && routerTo(routeEnum.loginPath)
        cancel && store.commit('removeRedirectURL')
      }
    })
  } else {
    // 直接跳转登录页
    routerTo(routeEnum.loginPath)
  }
}

// 判断是否跳转的是tabbar的路由
export const hasTabbar = function(url) {
  // 检测是否是白名单中的路由url(即tabbar中的路由url)
  let isInclude = false
  for (let i = 0, length  = tabbarPaths.length; i < length; i++) {
    const tabbarItem = tabbarPaths[i]
    if (url.indexOf(tabbarItem) !== -1) {
      isInclude = true
      break
    }
  }
  return isInclude
}

// 不需要验证登录后跳转--封装函数
const _noNeedLogin = function(url) {
  const { route, query } = getRoute()
  const queryStr = setObjToString(query)
  let fullPath = '/' + route + queryStr
  // 跳转登录页面--需要将当前页面存缓存，登录成功之后需要重新定向到该页面
  if (url === routeEnum.loginPath) {
    // 若当前已登录，仍跳转登录页，拦截
    if (isLogin()) return
  }
  store.commit('setRouteStack', fullPath)
  const isInclude = hasTabbar(url)
  isInclude ? uni.switchTab({ url }) : uni.navigateTo({ url })
}

// 路由跳转
export const routerTo = function(options) {
  // options url、needLogin、loginModal
  let url = ''// 跳转路径
  let needLogin = false // 是否需要验证登录后跳转
  let modal = true // 登录时，是否弹窗--默认弹窗
  
  if (isString(options) || isObject(options)) {
    if (isString(options)) {
      url = options
    } else {
      if (Object.prototype.hasOwnProperty.call(options, 'url')) {
        url = options.url
      } else {
        throw new Error('Options must have a url!')
      }

      if (Object.prototype.hasOwnProperty.call(options, 'needLogin')) needLogin = options.needLogin

      if (Object.prototype.hasOwnProperty.call(options, 'modal')) modal = options.modal
    }
  
    // 需要验证登录后跳转
    if (needLogin) {
      // 已经登录--直接跳转
      if (isLogin()) {
        const isInclude = hasTabbar(url)
        isInclude ? uni.switchTab({ url }) : uni.navigateTo({ url })
      } else {
        store.commit('setRedirectURL', url)
        hasModal(modal)
      }
    } else {
      // 不需要登录
      _noNeedLogin(url)
    }
  } else {
    throw new Error('param must be string or object!')
  }
}

// 路由返回
export const routerBack = function() {
  const { route, query, routes } = getRoute()
  // 需要分开处理H5和小程序的路由返回
  // H5的路由返回不会有动画--且用户可以刷新当前页面之后仍可以返回之前访问过的页面
  // 小程序的路由返回有动画--且用户刷新时即重新进入小程序，不存在H5刷新之后仍可以访问之前访问过的页面情况

  // 当前页面参数
  const currentQueryStr = setObjToString(query)
  // 当前页面url
  const currentPath = route + currentQueryStr

  // 小程序
  // #ifndef H5
  // 当前路由栈是否有其他路由组件
  if (routes.length > 1) {
    for (let i = routes.length - 1; i >= 0; i--) {
      const routeItem = routes[i]
      // 即将返回页面参数
      const backQueryStr = setObjToString(routeItem.options)
      // 即将返回页面url
      const backPath = routeItem.route + backQueryStr
      // 要返回的页面是当前页面时/已登录且要返回的是登录页面不跳
      if ((currentPath === backPath) || (isLogin() && backPath.indexOf(routeEnum.loginPath) !== -1)) {
        // 删除vuex中的路由栈
        store.commit('removeRouteStack', backPath)
        continue
      } else {
        // TODO:这里需要注意可能路由跳转了，但是并没有执行删除vuex中的路由栈
        // 删除vuex中的路由栈
        store.commit('removeRouteStack', backPath)
        uni.navigateBack({
          delta: routes.length - i - 1
        })
        return
      }
    }
  } else {
    // 当前只有一个路由组件--跳转首页
    store.commit('clearRouteStack')
    uni.switchTab({ url: routeEnum.indexPath })
  }
  // #endif

  // H5路由跳转
  // #ifdef H5
  const routeStack = store.getters.routeStack
  if (routeStack.length > 1) {
    for (let i = routeStack.length - 1; i >= 0; i--) {
      const backPath = routeStack[i]
      // 要返回的页面是当前页面时/已登录且要返回的是登录页面不跳
      if (('/' + currentPath === backPath) || (isLogin() && backPath.indexOf(routeEnum.loginPath) !== -1)) {
        store.commit('removeRouteStack', backPath)
        continue
      } else {
        const isInclude = hasTabbar(backPath)
        if (isInclude) {
          uni.switchTab({ url: backPath })
        } else {
          uni.redirectTo({
            url: backPath
          })
        }
        return
      }
    }
  } else {
    // 只有一个路由栈了，且不是首页则跳首页
    store.commit('clearRouteStack')
    uni.switchTab({ url: routeEnum.indexPath })
  }
  // #endif
}

// 路由重定向--该方法估计会很少用--目前只有在登录成功之后重定向回原来的页面
export const routerRedirect = function() {
  const redirectPath = store.getters.redirectURL
  if (redirectPath) {
    store.commit('removeRedirectURL')
    uni.redirectTo({
      url: redirectPath
    })
  } else {
    const { routes } = getRoute()
    routes.length > 0 ? uni.navigateBack(routes.length) : uni.redirectTo({ url: routeEnum.indexPath })
  }
}

/**
* @description 全局判断是否登录--验证当前页面操作的登录--不需要跳转到下一页面时使用
* @param {Boolean} 是否弹窗询问
* @returns {Boolean} true--已登录，false--未登录
*/
export const hasLogin = function(modal) {
  if (isLogin()) {
    return true
  } else {
    hasModal(modal)
    return false
  }
}